/*
 * This file is part of monitor_agent.
 * Copyright (c) 2018. Author: yinjia evoex123@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.  This program is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.  You should have received a copy
 * of the GNU Lesser General Public License along with this program.  If not,
 * see <http://www.gnu.org/licenses/>.
 */
package main

import (
	"bufio"
	"fmt"
	"monitor_agent/inc"
    "monitor_agent/module"
    "monitor_agent/utils"
	"os"
	"regexp"
	"strings"
	"time"
)

var FIELDS = []string{"bytes", "packets", "errs", "dropped",
	"fifo.errs", "frame.errs", "compressed", "multicast",
	"bytes", "packets", "errs", "dropped",
	"fifo.errs", "collisions", "carrier.errs", "compressed"}
type ifstatPlugin string
var IFSTAT_DEFAULT_COLLECTION_INTERVAL = 15

func main() {
	ifstat()
}

func (p ifstatPlugin) Collect() {
	defer inc.Wg.Done()
	select {
	case _ = <-inc.Shutdown:
		//We're done!
		return
	default:
		ifstat()
	}
}

func ifstat() {
	host, _ := inc.ConfObject.GetString("ServerName")
	metricPrefix := "apps.backend." + host + "."
	collectionInterval := IFSTAT_DEFAULT_COLLECTION_INTERVAL
	f_netdev, err := os.Open("/proc/net/dev")
	if err != nil {
		utils.Log(utils.GetLogger(), "ifstat][err:"+err.Error(), 2, 1)
	}
	for {
		ts := time.Now().Unix()
		f_netdev.Seek(0, 0)
		scanner := bufio.NewScanner(f_netdev)
		for scanner.Scan() {
			line := scanner.Text()
			reg := regexp.MustCompile(`\s*(eth?\d+ |em\d+_\d+/\d+ | em\d+_\d+ | em\d+ |p\d+p\d+_\d+/\d+ | p\d+p\d+_\d+ | p\d+p\d+ |(?:(?:en|sl|wl|ww)(?:b\d+ |c[0-9a-f]+ |o\d+(?:d\d+)? |s\d+(?:f\d+)?(?:d\d+)? |x[0-9a-f]+ |p\d+s\d+(?:f\d+)?(?:d\d+)? |p\d+s\d+(?:f\d+)?(?:u\d+)*(?:c\d+)?(?:i\d+)?))):(.*)`)
			data := reg.FindAllStringSubmatch(line, -1)
			if data == nil || len(data[0]) < 3 {
				continue
			}
			fmt.Println(data[0][1])
			intf := data[0][1]
			stats_fields := data[0][2]
			stats := strings.Fields(stats_fields)
			for i := 0; i < 16; i++ {
				//print("proc.net.%s %d %s iface=%s direction=%s"
				//% (FIELDS[i], ts, stats[i], intf, direction(i)))
				fmt.Print("ifstat proc.net.%v %v %v iface=%v direction=%v", FIELDS[i], ts, stats[i], intf, direction(i))
				if inc.QueueType == 0 {
				    inc.MsgQueue <- fmt.Sprintf("ifstat %vproc.net.%v %v %v iface=%v direction=%v", FIELDS[i], metricPrefix, ts, stats[i], intf, direction(i))
                } else if inc.QueueType == 1 {
                    module.DisruptorPublish(inc.Writer, inc.Reader, fmt.Sprintf("ifstat %vproc.net.%v %v %v iface=%v direction=%v", FIELDS[i], metricPrefix, ts, stats[i], intf, direction(i)))
                }
			}
			//fields := strings.Fields(data[0][2])

			//# We just care about ethN and emN interfaces.  We specifically
			//# want to avoid bond interfaces, because interface
			//# stats are still kept on the child interfaces when
			//# you bond.  By skipping bond we avoid double counting.
		}
		time.Sleep(time.Second * time.Duration(collectionInterval))
	}
}

func direction(i int) string {
	if i >= 8 {
		return "out"
	} else {
		return "in"
	}

}

var IfstatSo ifstatPlugin
